package com.hzw.net.page

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
import androidx.fragment.app.Fragment
import androidx.viewbinding.ViewBinding
import com.hzw.net.page.layout.AbsTitleLayout
import com.hzw.net.page.status.*
import com.hzw.net.vm.IView

/**
 *
 * @Author:         HuaZhongWei
 * @CreateDate:     2020/11/4 15:44
 *
 * @Description:    所有Fragment的基类，包含了界面组成，状态栏的改变
 *
 */
abstract class BaseFragment<VB : ViewBinding> : Fragment(), IView {

    open val isNeedPageStatusManager: Boolean = true

    var statusManager: PageStatusManager? = null

    /**
     * 不能像layoutResId一样，直接abstract或open直接重写属性
     * 因为会子类重复创建4次，并且最后引用不一致，造成内部方法执行无效
     * 具体原因不清楚，可能跟kotlin的多态有关
     * 最后与Java保持一致的多态操作，重写方法，不重写属性
     */
    private var titleLayout: AbsTitleLayout? = null

    var isNeedRefreshOnResume = false

    private var isLoaded = false

    private var _binding: VB? = null

    protected val binding: VB
        get() = _binding!!

    abstract fun getViewBinding(): VB

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        _binding = getViewBinding()
        return initPage(inflater, container)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        initSpecialEvent()
        init(savedInstanceState)
    }

    override fun onResume() {
        super.onResume()
        if (isNeedRefreshOnResume && isLoaded) {
            onResumeRefresh()
            isNeedRefreshOnResume = false
        }

        if (!isLoaded) {
            firstVisible()
            isLoaded = true
        }
    }

    /**
     * 初始化一些特殊的事件，放在最底层初始化界面之前
     */
    open fun initSpecialEvent() {

    }

    /**
     * 仅初始化一些与界面相关的操作
     */
    abstract fun init(savedInstanceState: Bundle?)


    open fun onResumeRefresh() {

    }

    open fun firstVisible() {

    }

    private fun initPage(inflater: LayoutInflater, container: ViewGroup?): View {
        titleLayout = initTitleLayout()
        return if (titleLayout != null) { //有标题，那么这里必须套一层，这样保证
            if (isNeedPageStatusManager) { // 需要 loading、空、错误等界面
                createPageStateManager()
                titleLayout!!.initUI()
                statusManager?.rootLayout!!
            } else {  //不需要PageStateManager, 没有loading, 空，错误等界面
                val view = createContentLayout()
                titleLayout!!.initUI()
                view
            }
        } else { //没有标题，那么直接使用，这样可以相比之前减少一层布局，提高性能
            if (isNeedPageStatusManager) { // 需要 loading、空、错误等界面
                createPageStateManager()
                statusManager?.rootLayout!!
            } else { //不需要PageStateManager, 没有loading, 空，错误等界面
//                getRootView()
                binding.root
            }
        }
    }

    private fun createContentLayout(): View {
        //第一步：创建容器跟布局
        val rootLayout = LinearLayout(requireContext()).apply {
            orientation = LinearLayout.VERTICAL
        }

        // 第二步：加入标题
        val titleParams = LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.WRAP_CONTENT
        )
        rootLayout.addView(titleLayout!!.rootView, titleParams)

        // 第三步：加入内容
        val contentParams = LinearLayout.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT,
            ViewGroup.LayoutParams.MATCH_PARENT
        )
        rootLayout.addView(binding.root, contentParams)
        return rootLayout
    }

    private fun createPageStateManager() {
        statusManager = initStateManager() ?: PageStatusManager.Builder(requireContext())
            .title(titleLayout?.rootView)
            .content(binding.root)
            .loading(onCreateLoading())
            .empty(onCreateEmpty())
            .error(onCreateError())
            .build()
    }

    open fun initTitleLayout(): AbsTitleLayout? {
        return null
    }

    open fun initStateManager(): PageStatusManager? {
        return null
    }

    override fun showLoading(isHideOther: Boolean) {
        if (isResumed) {
            statusManager?.showLoading(isHideOther)
        }
    }

    override fun hideLoading() {
        statusManager?.hideLoading()
    }

    override fun showContent() {
        statusManager?.showContent()
    }

    override fun showEmpty() {
        statusManager?.showEmpty(0, "", null)
    }

    override fun showEmpty(imageResId: Int, tipText: String?, retryText: String?) {
        statusManager?.showEmpty(imageResId, tipText ?: "", retryText)
    }

    override fun showError() {
        statusManager?.showEmpty(0, "", null)
    }

    override fun showError(imageResId: Int, tipText: String?, retryText: String?) {
        statusManager?.showEmpty(imageResId, tipText ?: "", retryText)
    }

    override fun handleSpecialEvent(code: Int) {

    }

    override fun onCreateLoading(): ILoadingStatus {
        return LoadingPageStatus(requireContext())
    }

    override fun onCreateEmpty(): IAbnormalStatus {
        return AbnormalPageStatus(requireContext(), refresh = {
            onRefreshForEmpty(it)
        }, retry = {
            onRetryForEmpty()
        })
    }

    override fun onCreateError(): IAbnormalStatus {
        return AbnormalPageStatus(requireContext(), refresh = {
            onRefreshForEmpty(it)
        }, retry = {
            onRetryForEmpty()
        })
    }

    override fun onDestroyView() {
        super.onDestroyView()
        isLoaded = false
        _binding = null
    }
}